package tech.waterism.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;

/**
 * JSON文件转换工具类
 * 用于将包含双重编码JSON字符串的txt文件转换为标准的JSON文件
 * 
 * 问题说明：
 * 原始txt文件中某些字段的值是JSON字符串，如：
 * "dt":"[\"2025-05-06 08:00:00\",\"2025-05-06 11:00:00\"]"
 * 
 * 转换后标准JSON：
 * "dt":["2025-05-06 08:00:00","2025-05-06 11:00:00"]
 * 
 * @author tech.waterism
 * @date 2025-11-10
 */
public class JsonFileConverter {
    
    private static final Logger LOGGER = Logger.getLogger(JsonFileConverter.class);
    private static final ObjectMapper MAPPER = new ObjectMapper();
    
    /**
     * 转换单个文件
     * 
     * @param inputFile 输入的txt文件路径
     * @param outputFile 输出的json文件路径
     * @throws IOException 文件读写异常
     */
    public static void convertFile(String inputFile, String outputFile) throws IOException {
        LOGGER.info("开始转换文件: " + inputFile);
        
        // 读取原始JSON内容
        String content = Files.readString(Paths.get(inputFile));
        
        // 转换JSON格式
        String cleanedJson = convertProblematicJson(content);
        
        // 写入新文件
        Files.writeString(Paths.get(outputFile), cleanedJson);
        
        LOGGER.info("转换完成，输出文件: " + outputFile);
    }
    
    /**
     * 批量转换指定目录下的所有txt文件
     * 
     * @param inputDir 输入目录
     * @param outputDir 输出目录
     * @throws IOException 文件读写异常
     */
    public static void convertDirectory(String inputDir, String outputDir) throws IOException {
        File dir = new File(inputDir);
        if (!dir.exists() || !dir.isDirectory()) {
            throw new IllegalArgumentException("输入目录不存在: " + inputDir);
        }
        
        // 创建输出目录
        Path outputPath = Paths.get(outputDir);
        if (!Files.exists(outputPath)) {
            Files.createDirectories(outputPath);
        }
        
        // 遍历所有txt文件
        File[] files = dir.listFiles((d, name) -> name.toLowerCase().endsWith(".txt"));
        if (files == null || files.length == 0) {
            LOGGER.warn("目录中没有找到txt文件: " + inputDir);
            return;
        }
        
        LOGGER.info("找到 " + files.length + " 个txt文件，开始批量转换...");
        
        for (File file : files) {
            String fileName = file.getName();
            String outputFileName = fileName.substring(0, fileName.lastIndexOf('.')) + ".json";
            String outputFile = outputDir + File.separator + outputFileName;
            
            try {
                convertFile(file.getAbsolutePath(), outputFile);
            } catch (Exception e) {
                LOGGER.error("转换文件失败: " + fileName, e);
            }
        }
        
        LOGGER.info("批量转换完成！");
    }
    
    /**
     * 转换有问题的JSON字符串
     * 识别字符串值中的JSON数组并将其解析为真正的数组
     * 
     * @param problematicJson 有问题的JSON字符串
     * @return 清理后的JSON字符串
     * @throws IOException JSON解析异常
     */
    private static String convertProblematicJson(String problematicJson) throws IOException {
        JsonNode rootNode = MAPPER.readTree(problematicJson);
        
        if (rootNode.isObject()) {
            ObjectNode objectNode = (ObjectNode) rootNode;
            Iterator<String> fieldNames = objectNode.fieldNames();
            
            while (fieldNames.hasNext()) {
                String fieldName = fieldNames.next();
                JsonNode fieldValue = objectNode.get(fieldName);
                
                // 递归处理对象和数组
                if (fieldValue.isObject()) {
                    String converted = convertProblematicJson(fieldValue.toString());
                    objectNode.set(fieldName, MAPPER.readTree(converted));
                } else if (fieldValue.isArray()) {
                    ArrayNode arrayNode = (ArrayNode) fieldValue;
                    for (int i = 0; i < arrayNode.size(); i++) {
                        JsonNode element = arrayNode.get(i);
                        if (element.isObject() || element.isArray()) {
                            String converted = convertProblematicJson(element.toString());
                            arrayNode.set(i, MAPPER.readTree(converted));
                        } else if (element.isTextual()) {
                            arrayNode.set(i, tryParseJsonString(element.textValue()));
                        }
                    }
                } else if (fieldValue.isTextual()) {
                    // 尝试解析字符串值
                    objectNode.set(fieldName, tryParseJsonString(fieldValue.textValue()));
                }
            }
        }
        
        return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);
    }
    
    /**
     * 尝试将字符串解析为JSON
     * 如果字符串是有效的JSON格式（数组或对象），则解析返回；否则返回原字符串节点
     * 
     * @param text 待解析的字符串
     * @return 解析后的JsonNode
     */
    private static JsonNode tryParseJsonString(String text) {
        if (text == null || text.isEmpty()) {
            return MAPPER.getNodeFactory().textNode(text);
        }
        
        String trimmed = text.trim();
        
        // 检查是否像JSON数组或对象
        if ((trimmed.startsWith("[") && trimmed.endsWith("]")) ||
            (trimmed.startsWith("{") && trimmed.endsWith("}"))) {
            try {
                // 尝试解析为JSON
                return MAPPER.readTree(trimmed);
            } catch (IOException e) {
                // 不是有效的JSON，返回原字符串
                return MAPPER.getNodeFactory().textNode(text);
            }
        }
        
        // 不是JSON格式，返回原字符串
        return MAPPER.getNodeFactory().textNode(text);
    }
    
    /**
     * 主函数 - 用于命令行转换
     * 
     * 使用方式：
     * 1. 转换单个文件：
     *    java tech.waterism.util.JsonFileConverter file input.txt output.json
     * 
     * 2. 转换整个目录：
     *    java tech.waterism.util.JsonFileConverter dir /path/to/input /path/to/output
     * 
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("用法:");
            System.out.println("  转换单个文件: java JsonFileConverter file <输入文件.txt> <输出文件.json>");
            System.out.println("  转换目录:     java JsonFileConverter dir <输入目录> <输出目录>");
            System.out.println();
            System.out.println("示例:");
            System.out.println("  单文件: java JsonFileConverter file input.txt output.json");
            System.out.println("  目录:   java JsonFileConverter dir ./resources ./output");
            return;
        }
        
        try {
            String mode = args[0];
            
            if ("file".equalsIgnoreCase(mode)) {
                if (args.length < 3) {
                    System.err.println("错误: 文件模式需要指定输入文件和输出文件");
                    return;
                }
                convertFile(args[1], args[2]);
                System.out.println("✓ 文件转换成功!");
                
            } else if ("dir".equalsIgnoreCase(mode)) {
                if (args.length < 3) {
                    System.err.println("错误: 目录模式需要指定输入目录和输出目录");
                    return;
                }
                convertDirectory(args[1], args[2]);
                System.out.println("✓ 目录转换成功!");
                
            } else {
                System.err.println("错误: 未知模式 '" + mode + "'，请使用 'file' 或 'dir'");
            }
            
        } catch (Exception e) {
            System.err.println("✗ 转换失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

